home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume25 / QBATCH / part04 < prev    next >
Encoding:
Text File  |  1991-11-04  |  48.3 KB  |  1,396 lines

  1. Newsgroups: comp.sources.misc
  2. From: alan@tharr.UUCP (Alan Saunders)
  3. Subject:  v25i023:  QBATCH - a queued batch processing system for UNIX, Part04/06
  4. Message-ID: <1991Nov5.034825.5074@sparky.imd.sterling.com>
  5. X-Md4-Signature: 500e591bea767e1c667077198f0e0979
  6. Date: Tue, 5 Nov 1991 03:48:25 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: alan@tharr.UUCP (Alan Saunders)
  10. Posting-number: Volume 25, Issue 23
  11. Archive-name: QBATCH/part04
  12. Environment: UNIX
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then unpack
  16. # it by saving it into a file and typing "sh file".  To overwrite existing
  17. # files, type "sh file -c".  You can also feed this as standard input via
  18. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  19. # will see the following message at the end:
  20. #        "End of archive 4 (of 6)."
  21. # Contents:  NEWS doc/chap.05 doc/chap.06 man/qc.l src/config.c
  22. #   src/config.h src/jj.c
  23. # Wrapped by root@vfib_d on Thu Oct 31 15:46:40 1991
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'NEWS' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'NEWS'\"
  27. else
  28. echo shar: Extracting \"'NEWS'\" \(6096 characters\)
  29. sed "s/^X//" >'NEWS' <<'END_OF_FILE'
  30. X    Current release of QBATCH version 2.0 Aug 30 1991
  31. X
  32. X    The QBATCH system and its related programs were
  33. X    written by Alan D. Saunders and are
  34. X    Copyright (c) Vita Services Ltd. 1990 and
  35. X    Copyright (c) Vita Fibres Ltd. 1991
  36. X
  37. X    PLEASE read the NOTICE file for details.
  38. X
  39. ORIGINS.
  40. X
  41. In 1989 we (as a company) were faced with porting all our software from
  42. a proprietary operating system to UNIX.  Most of the applications were
  43. based on a two layer transaction processing system which made heavy
  44. use of the system's batching system.  Under UNIX, we attempted to use
  45. the print spooling system to emulate batch queuing with limited 
  46. success.  I undertook to write a batch queueing system which included
  47. the best of the functions of the old system (plus a lot of enhancements)
  48. before the new UNIX systems went live.  The original system was 
  49. implemented in May 1990, the first Sun SPARCstation went live in the
  50. October.  Apart from incremental enhancements, QBATCH has been going
  51. strong since then (now live on ten systems in the company).
  52. X
  53. In May (or June) 1991 I read a posting in alt.sources.wanted from 
  54. someone looking for a batch queueing system.  Simultaneously, the
  55. software house who's tools we used for the conversion, expressed an
  56. interest. (They were doing further ports for other users of the same
  57. proprietary kit.)  I therefore 'shar'ed it up and distributed it as
  58. it then stood.  (including posting it in alt.sources).  As a result of
  59. this, I have had a great deal of feedback:
  60. X
  61. X---------------------- The story continues ----------------:-
  62. X
  63. QBATCH has been totally revamped since the last release.  This was done
  64. in the light of difficulties experienced by several people in trying to
  65. compile and install it on their systems.  QBATCH is now far more easily
  66. configured for the target platform, and some previously hard-wired
  67. facilities have been made configurable.
  68. X
  69. All (I hope) areas where different platforms provide differing support
  70. have been moved to a new file config.c.  Which of each of the various
  71. options is used is determined by defines in config.h. (file locking,
  72. signal handling, and process group handling).
  73. X
  74. Configuration options for QBATCH itself (the paths for the spool files 
  75. and the queues themselves) are contained in the first few lines of
  76. qbatch.h.
  77. X
  78. Support for systems that can't exec scripts (containing #!/bin/sh for
  79. example). Now qp reads the first line of the jcl file and execs the
  80. program stated therein, instead of the file itself.
  81. X
  82. The shell under which the batch job is run can be specified when
  83. submitting the job using the -s<shell> option, thus allowing for
  84. example 'js -s/usr/local/bin/perl -n <jobname> <queue> <jclfile>'
  85. Originally, the batch shell used was always the bourne shell. 
  86. X(this is still the default).
  87. X
  88. XEnvironment variables can be prevented from being passed to the batch
  89. job.  By default, all environment variables in force when a job is
  90. submitted are passed through, and form part of the environment of the
  91. running job.  Now, if a .qxenv file exists in the same directory as the
  92. queues themselves, then any non- blank lines (not starting with '#')
  93. are taken to contain (one per line) the names of environment variables
  94. which are NOT to be passed to the batch job.
  95. X
  96. X
  97. A. D. Saunders August 30 1991
  98. X
  99. X----------------------------------------------------------------------
  100. X
  101. September 18 1991:
  102. X
  103. Much work has been carried out resolving porting problems .. current release
  104. incorporates these changes.
  105. X
  106. Thanks to:
  107. X
  108. Chris Metzler (metzler@elvis.physics.lsa.umich.edu)
  109. X(Port to Stardent S5000)
  110. X
  111. John Whitley  (G.W. Systems ltd., Tring Herts UK.)
  112. X(Ports to I386 architecture and HP/UX)
  113. X
  114. X..ADS.
  115. X
  116. September 23 1991:
  117. X
  118. A degree of profile timing has been introduced, real (wall clock),
  119. user and system times taken by queued jobs are now reported in the
  120. monitor, and a summary report may be requested with the (new) -s option
  121. of qf.  This reports the totals of each time, and the average per job.
  122. X
  123. X..ADS
  124. X
  125. October 3 1991
  126. X
  127. Profile timing extended to include queueing time (time on queue before
  128. processing).
  129. X
  130. Caught a race condition bug (and learnt a bit more about mandatory and
  131. advisory file locking!!) js was telling qp that a job was available
  132. before unlocking the queue. qp was receiving the signal but couldn't
  133. open the queue to get the job.
  134. X(Thanks to John Whitley for this one)
  135. X
  136. Implemented code which should (?) prevent qp being initialised twice 
  137. for the same queue. removed -r (restart) option from qp.
  138. X
  139. Implemented code to allow optional queues to have "NONE" as the default
  140. monitor.  In these cases js will now fail if the queue has "NONE" for
  141. the monitor and the user submitting the job has not specified a 
  142. monitor on the command line, and their MONITOR environment variable
  143. is not set.
  144. X
  145. modified qf to look for the environment variable if default monitor
  146. is "NONE".
  147. X
  148. Modified qc to allow changes to existing queues (priority, monitor etc.)
  149. X
  150. Modified js to replace the default shell with the first line in
  151. X.<queuename>rc (fixed context queues) if it is of the form:
  152. X#!<pathspec> [options]
  153. and if the -s option is not used.
  154. X
  155. Tarted up documentation, rehashed man pages to account for above changes.
  156. X
  157. Released current version as beta release to local sites.
  158. X
  159. X..ADS
  160. X
  161. X9 October 1991 bug js coredumps for fixed context queues where
  162. X#QCONTEXT is defined. Discovered a 'feature':-) in Sun's 
  163. implementation re XPG3 (tm). the core dump was at the following:
  164. X
  165. i = sscanf (buff, "%s %d %d", rcmd, &jobuid, &jobgid);
  166. X
  167. If jobuid and jobgid are defined (per X-OPEN) as uid_t, and gid_t,
  168. it results in a bus error!
  169. X
  170. bug fixed by using a pair of ints for the sscanf, and moving them
  171. to job[ug]id.
  172. X
  173. X16 October 1991 ..
  174. Added -n option to qf to get the priority or nice value.
  175. Added -l option to qf to list summary of flags.
  176. Added qt program to test queue flags.
  177. added qa script to list queues available to a user.
  178. Brought man pages up to date.
  179. X
  180. X..ADS
  181. X
  182. X31 October 1991
  183. Wrote documentation... This is preliminary, and not formatted.
  184. My knowledge of [nt]roff is limited to the creation of man pages,
  185. and my knowledge of [La]TeX is even less.... Any volunteers?
  186. X
  187. X..ADS
  188. END_OF_FILE
  189. if test 6096 -ne `wc -c <'NEWS'`; then
  190.     echo shar: \"'NEWS'\" unpacked with wrong size!
  191. fi
  192. # end of 'NEWS'
  193. fi
  194. if test -f 'doc/chap.05' -a "${1}" != "-c" ; then 
  195.   echo shar: Will not clobber existing file \"'doc/chap.05'\"
  196. else
  197. echo shar: Extracting \"'doc/chap.05'\" \(6414 characters\)
  198. sed "s/^X//" >'doc/chap.05' <<'END_OF_FILE'
  199. X
  200. X             QBATCH  a queued batch processing system for UNIX
  201. X
  202. X
  203. X         The QBATCH system and its related programs were
  204. X         written by Alan D. Saunders and are
  205. X         Copyright (c) Vita Services Ltd. 1990 and
  206. X         Copyright (c) Vita Fibres Ltd. 1991
  207. X
  208. X5. MONITORS.
  209. X
  210. X    A monitor in QBATCH terms, is a file to which the combined stdout and
  211. X    stderr output of a job is written.  In the absence of any other direction,
  212. X    the monitor for a given queue will have a name <queuename>.mon, and reside
  213. X    in the spooling directory (SPOOLPATH) for that queue. (more will be said
  214. X    later on the location of and access to monitors.)
  215. X
  216. X    When the queue process engine (qp) for a given queue receives a job to be
  217. X    processed, it will open the monitor and write a timestamp in it before the
  218. X    job is forked.  After forking, and before executing the job, qp will
  219. X    attach stdout and stderr to the open monitor. When the job is complete
  220. X    (or is killed) and the child process exits, qp will again write a timestamp
  221. X    in the monitor .  The profile timing calculated by qp is also written into
  222. X    the monitor before closing it (as well as accumulated in the queue header)
  223. X    viz:
  224. X
  225. X    ##
  226. X    ## Queue sopt entry 1 (uid = 0 : root) Job: QBATCH test file
  227. X    ## Started Fri Oct 11 11:18:32 1991
  228. X    ##
  229. X
  230. X    [ here would appear the stdout and stderr of the job ]
  231. X
  232. X    ##
  233. X    ## Queue sopt entry 1 (uid = 0 : root) Job: QBATCH test file
  234. X    ## stopped Fri Oct 11 11:18:43 1991
  235. X    ## Times:- Queued:      1:54:34.18   Real:           10.53
  236. X    ##           User:            0.06 System:            0.28
  237. X    ##  (Job exited with status 0)
  238. X    ##
  239. X
  240. X    The monitor therefore not only serves to record the output of a job, but
  241. X    also to give some indication of it's performance, and resource usage.
  242. X
  243. X    Normally, queue default monitors will be publicly readable, to allow users
  244. X    to check on the progress of their jobs.  This obviously may be changed by
  245. X    the local system administrator, particularly in the case of monitors
  246. X    potentially containing sensitive information.  I might suggest however that
  247. X    a program which puts sensitive information to stdout or stderr should be
  248. X    looked at.
  249. X
  250. X    The monitor for a queue may be accessed using qf to provide the pathspec.
  251. X    qf -q returns the queue default monitor, and
  252. X    qf -m returns the monitor of the currently running job if there is one,
  253. X    otherwise the queue default monitor.
  254. X    so:
  255. X    more `qf -m work`
  256. X    will allow the user to examine the monitor for the job running in the work
  257. X    queue, and
  258. X    tail -f `qf -m work`
  259. X    will allow the user to watch the progress of the currently running job.
  260. X
  261. X    The default monitor for a queue is defined using qc with the -m option.
  262. X    If this option is not used, the monitor is created as above in the queue
  263. X    spooling directory.  The -m option will cause the absolute pathspec of the
  264. X    option value to be used.  If this value is a file, that will be used, If it
  265. X    is a directory, then the file <queuename>.mon will be used in that
  266. X    directory.
  267. X
  268. X    Users submitting jobs to the queue can also use a -m option to js to
  269. X    overrule the default queue monitor. (the rules are the same).
  270. X
  271. X    If a user submitting a job has a MONITOR environment variable set, then in
  272. X    the absence of a -m option to js, this will be used to determine the monitor
  273. X    for the job.
  274. X
  275. X    So, the monitor for a job can be determined several ways:
  276. X    1.    Defaulted when the queue was created.
  277. X    2.    Specified when the queue was created or amended.
  278. X    3.  From the environment of the submitting user.
  279. X    4    Specified to js when the job is submitted.
  280. X
  281. X    In each case, if the monitor determined is a file, that will be used.  If
  282. X    it is a directory, a file <queuename>.mon will be used in that directory.
  283. X    In the above list, if more than one case is available a source later in the
  284. X    list will overrule a source earlier (a monitor sourced by specifying -m to
  285. X    js will always be used even if a MONITOR environment variable is set.)
  286. X
  287. X    If a default monitor of "NONE" is specified to qc for either a new or
  288. X    existing queue:
  289. X    qc -m NONE <queuename>
  290. X    Then there will be no default monitor.  js then expects the user on
  291. X    submitting a job, to provide a pathspec for a monitor, either through
  292. X    the -m option of js, or through an environment variable "MONITOR".  It
  293. X    WILL NOT allow the job to be submitted if a monitor is not specified.
  294. X    If you wish to set up an environment where each user or group of users
  295. X    has their own private monitors for each queue they use, then set up in
  296. X    their .cshrc, .login, or .profile, an environment variable pointing to
  297. X    a DIRECTORY in their own filespace.  Monitors named for the queues
  298. X    (viz: <queuename>.mon) will be created and used in that directory.
  299. X    WARNING!
  300. X    1. Such private monitors are ONLY used for queues whose default monitor
  301. X       is NONE.
  302. X    
  303. X    2. Any profile information stored in the monitors will be split up 
  304. X       across several directories, thus making accounting and tuning more
  305. X       difficult.
  306. X    3. using 'more `qf -m <queuename>`' may give startling results when
  307. X       used for troubleshooting.  (The result will depend on the setting
  308. X       of YOUR MONITOR environment variable, and may not have any
  309. X       relationship to the job you wish to check).
  310. X    
  311. X    Monitors, particularly those of active queues can expand, sometimes quite
  312. X    alarmingly.  The system administrator does need to keep a check on them.
  313. X    Local rules and conventions may vary depending on the requirements to keep
  314. X    monitors for post-operative analysis, and or accounting, but something
  315. X    should be done to prevent them getting out of hand.  One way, (used on our
  316. X    sites) is to 'age' the monitors on a daily basis using cron.  A six (or
  317. X    more or less depending on requirement) day cycle is used, and the monitors
  318. X    for each queue are copied to a history directory and numbered 
  319. X    <queuename>.mon.1
  320. X    <queuename>.mon.2 
  321. X    ...
  322. X    <queuename>.mon.6
  323. X    On a daily basis, the earliest monitor (6 in this case) is removed and the
  324. X    remaining monitors are renamed:
  325. X    5->6
  326. X    4->5
  327. X    ...
  328. X    1->2
  329. X    and the current monitor is copied in as <queuename>.mon.1.
  330. X    The 'live' monitor can then be truncated (cat /dev/null><monitorspec>).
  331. X    This approach at least keeps the problem manageable.
  332. X
  333. END_OF_FILE
  334. if test 6414 -ne `wc -c <'doc/chap.05'`; then
  335.     echo shar: \"'doc/chap.05'\" unpacked with wrong size!
  336. fi
  337. # end of 'doc/chap.05'
  338. fi
  339. if test -f 'doc/chap.06' -a "${1}" != "-c" ; then 
  340.   echo shar: Will not clobber existing file \"'doc/chap.06'\"
  341. else
  342. echo shar: Extracting \"'doc/chap.06'\" \(6248 characters\)
  343. sed "s/^X//" >'doc/chap.06' <<'END_OF_FILE'
  344. X             QBATCH .. a queued batch processing system for UNIX
  345. X
  346. X
  347. X        The QBATCH system and its related programs were
  348. X        written by Alan D. Saunders and are
  349. X        Copyright (c) Vita Services Ltd. 1990 and
  350. X        Copyright (c) Vita Fibres Ltd. 1991
  351. X
  352. X6. CONFIGURATION.
  353. X
  354. X    When to use QBATCH.
  355. X    
  356. X    The strength of QBATCH, or for that matter any queued batch processing
  357. X    system is in it's use of queues.  If you have a series of jobs which
  358. X    cannot be processed in parallel, and must be processed in a given order,
  359. X    then a queued batch processing system is ideal.  You could write a
  360. X    (probably large) shell script to process the jobs in the right order, but
  361. X    what of jobs that don't always need to be run?  Do you change your
  362. X    accounting application run script at period end to add the period end jobs
  363. X    in the right order?  Do you have a separate period end script?  Or do you
  364. X    simply submit the jobs to a queue in the right order, and only submit
  365. X    those that need to be run this time?
  366. X
  367. X    QBATCH however is not limited to the application level.  There may be
  368. X    several reasons why jobs must not run in parallel.  Not least of these is
  369. X    system loading (or should I say overloading?).  If you have a large user
  370. X    base, all of whom are at liberty to chuck large jobs into the background,
  371. X    you'd better have an inexhaustible supply of cpu cycles and swap space for
  372. X    them.  You can however ease the processing load by having the jobs
  373. X    submitted to one or more background queues.  Which will cause more
  374. X    complaints, the odd user who has to wait a bit longer, or every user who
  375. X    has to wait whilst the system slowly dies?
  376. X
  377. X    How about resource sharing?  If you have a 50 Mb scratch partition, and
  378. X    100 users each want to create a 10 Mb scratch file, someone's going to be
  379. X    disappointed.  If however, those 100 jobs were shared over 5 queues, each
  380. X    user's job could quite happily create it's scratch file.
  381. X
  382. X    In short a queued batch processing system is desirable if:
  383. X
  384. X    A. There is a need to order a variable sequence of jobs which must not run
  385. X       in parallel.
  386. X
  387. X    B. There is a need for resource (including cpu and swap) sharing.
  388. X
  389. X    What do I call the queues?
  390. X
  391. X    QBATCH places no constraints on the naming of queues that the system
  392. X    itself doesn't place.  Ideally the queue name should be meaningful.  Only
  393. X    the first four characters of the name are used as a prefix for naming jcl
  394. X    files, and only 63 characters are catered for in the jcl spoolpath.  So
  395. X    for all round compatibility, it would be best if the names were around
  396. X    (or at least unique in the first) four characters.
  397. X
  398. X    Bearing in mind that the priority (or nice value) of the jobs being run in
  399. X    a queue can be specified, on our systems we have the following queues:
  400. X
  401. X    One for each of the online transaction processing systems e.g.
  402. X    sopt    (sales order processing)
  403. X
  404. X    One for any reports that CAN be produced concurrently with the online
  405. X    system e.g.
  406. X    sopr    (sales order processing reports)
  407. X
  408. X    One general purpose queue where reporting is none critical.
  409. X    work    (general purpose shared reporting queue)
  410. X
  411. X    One additional queue for sop dispatch notes (where with a lorry waiting,
  412. X    the throughput is time critical). This queue is set to a low nice value
  413. X    (high priority):
  414. X    sopq    (dispatch note queue)
  415. X
  416. X    In addition we have three general purpose queues shared by all users and
  417. X    applications, each running jobs at different priorities, and named for the
  418. X    throughput:
  419. X    fast    (for small, fast, high priority jobs)
  420. X    slow    (for big resource greedy jobs, runs at low priority)
  421. X    norm    (anything else)
  422. X
  423. X    How Many Queues?
  424. X
  425. X    QBATCH itself places no limit on the number of queues that may be
  426. X    configured.
  427. X
  428. X    Points to be taken into account are:
  429. X    a. The need to avoid concurrency in applications.
  430. X    b. The capacity of the system.
  431. X    c. The availability of potentially shared resources.
  432. X    d. Timing constraints.
  433. X
  434. X    a. At worst there will be a need for a queue per application where
  435. X       concurrency is a problem.  This may be tempered by timing constraints
  436. X       within the applications, for example if the batch work for one
  437. X       application tends to be in the morning, and for another in the
  438. X       afternoon, then there is probably no reason that they can't share a
  439. X       queue.
  440. X
  441. X    b & c.  As a 'rule of thumb' take the worst case requirement for an
  442. X       available resource (including cpu cycles and memory) and divide this
  443. X       into the total available of the corresponding resource.  This will give
  444. X       the number of queues, each running the worst case job that can be
  445. X       supported.  This is NOT a hard and fast rule.  By tuning the scripts
  446. X       which submit jobs, (and user training) it is possible to tune the system
  447. X       such that quick, non- cpu intensive (conservative rather than greedy)
  448. X       jobs are submitted to the same queue or group of queues.  If these are
  449. X       kept in separate queues from resource greedy jobs then the overall
  450. X       number of queues can be increased.  In other words, separate jobs
  451. X       requiring different types of resources into different queues, and tune
  452. X       the queue availability to the availability of the resources.
  453. X
  454. X    In general, there is no way that a systems administrator can ALWAYS get it
  455. X    right first time.  Take a reasonable estimate, implement it, and monitor
  456. X    it.  Be prepared to make changes as the actual requirements make
  457. X    themselves known.  It's probably better in the early stages to have too
  458. X    few queues rather than too many.  It's got to be easier to add a queue,
  459. X    and change one or two scripts to use the new queue, than to remove one,
  460. X    and try to remember which scripts used it!
  461. X
  462. X    If the system is a large multi user system, with a large user base, then
  463. X    perhaps a more systematical approach can be taken.  If the users are
  464. X    separated into groups, then access to queues may be restricted to certain
  465. X    groups by using fixed context queues.  Once sufficient queues to cater for
  466. X    the major systems jobs have been considered, then other general purpose
  467. X    queues could be configured on a group by group (individual or shared)
  468. X    basis.
  469. END_OF_FILE
  470. if test 6248 -ne `wc -c <'doc/chap.06'`; then
  471.     echo shar: \"'doc/chap.06'\" unpacked with wrong size!
  472. fi
  473. # end of 'doc/chap.06'
  474. fi
  475. if test -f 'man/qc.l' -a "${1}" != "-c" ; then 
  476.   echo shar: Will not clobber existing file \"'man/qc.l'\"
  477. else
  478. echo shar: Extracting \"'man/qc.l'\" \(5942 characters\)
  479. sed "s/^X//" >'man/qc.l' <<'END_OF_FILE'
  480. X.TH QC 8L "14 May 1991" QC "QUEUED BATCH PROCESSING SYSTEM"
  481. X.SH COPYRIGHT
  482. The
  483. X.B QBATCH
  484. system and its related programs are Copyright:
  485. X.br
  486. X(c) Vita Services Ltd. 1990
  487. X.br
  488. X(c) Vita Fibres Ltd. 1991
  489. X.SH NAME 
  490. X.BI qc
  491. X\- Queue create. create a batch processing queue, or alter it's default parameters.
  492. X.SH SYNOPSIS
  493. X.B qc
  494. X[
  495. X.B \- f
  496. X]
  497. X[
  498. X.BI \-m " monitor"
  499. X]
  500. X[
  501. X.BI \-p " priority"
  502. X]
  503. X[
  504. X.BI \-s " spoolpath"
  505. X]
  506. X.B qname
  507. X|[
  508. X.BI \-v
  509. X]
  510. X.SH DESCRIPTION
  511. A file of name qname will be created in QUEUEPATH (or in the
  512. directory to which it is a symbolic link). The file will
  513. contain a queue header record containing the information
  514. either as specified in the command line, or as the default values. The
  515. initial queue status flags will be set to allow entries
  516. to be submitted, and queue idle.
  517. X.sp
  518. If the queue already exists, the header contents will be changed to reflect
  519. the options specified on the command line.
  520. X.sp
  521. If the queue is to be a fixed context queue, (-f option) 
  522. X.B js
  523. X(the job submit program) will also expect to find a file .<qname>rc in the
  524. qbatch directory. This file is used to set up the environment in which all
  525. jobs in this queue will run, and controls access to the queue. The contents
  526. of the rc file are standard (see note) shell jcl, and are added to the beginning
  527. of jcl written for submitted jobs, except for certain statements as follows:
  528. X.TP 15
  529. X.B #QCONTEXT
  530. Defines the uid and gid under which jobs run in this queue
  531. will be processed. If this statement is not present, the submitting
  532. user's uid and gid will be used.
  533. X.TP
  534. X.B syntax:
  535. X#QCONTEXT <uid> <gid>
  536. X.br
  537. X.B NOTE:
  538. A fixed context queue with a QCONTEXT uid of 0 (root) is NOT permitted.
  539. X('0' in either field results in the original submittors uid (gid) being used).
  540. X.TP
  541. X.B #QUSERS
  542. If this statement is present, it defines a list of submitting user uids permitted
  543. to submit jobs to this queue.
  544. X.TP
  545. X.B syntax:
  546. X#QUSERS uid [uid ..]
  547. X.br
  548. X[#QUSERS uid [uid ..]]
  549. X.br
  550. A maximum of 10 uids may be present in a single QUSERS
  551. statement, but the statement may be repeated if there are to be more.
  552. X.TP
  553. X.B #QGROUPS
  554. If this statement is present, it defines a list of submitting user gids permitted
  555. to submit jobs to this queue.
  556. X.TP
  557. X.B syntax:
  558. X#QGROUPS gid [gid ..]
  559. X.br
  560. X[#QGROUPS gid [gid ..]]
  561. X.br
  562. A maximum of 10 gids may be present in a single QGROUPS
  563. statement, but the statement may be repeated if there are to be more.
  564. X.sp
  565. If neither QUSERS nor QGROUPS are present, any user may submit jobs to
  566. this queue.
  567. X.TP
  568. X.B #QGETENV
  569. Normally, the user environment is ignored in a fixed context queue. This statement 
  570. provides a mechanism for accessing environment variables, and passing them to the job.
  571. X.TP
  572. X.B syntax:
  573. X#QGETENV <envar>
  574. X.br
  575. X[#QGETENV <envar>]
  576. X.br
  577. X[..]
  578. X.TP
  579. example:
  580. X#QGETENV PRINTER
  581. X.br
  582. will ensure that the user's current setting of the PRINTER environment variable 
  583. is available when the job is running.
  584. X.TP 0
  585. Note that wherever a queue name is used, to create a monitor
  586. filename, or as a prefix for the jcl filename, only the
  587. first four characters are used. It is therefore advisable
  588. that queue names are restricted to four characters in 
  589. length.
  590. X.SH IMPORTANT NOTE
  591. Since the shell under which batch jobs will run is now definable at submit
  592. time (see js (l)), it should be noted that the jcl in a <qname>rc file should be
  593. of the correct syntax for the shell in use. This is only a problem where the -s option to 
  594. js is used. The 'default' shell for a fixed context queue may be forced by including
  595. X(as the FIRST line in the .<queuename>rc file) a line of the form
  596. X.br
  597. X#!<shell pathspec>
  598. X.br
  599. This will then override /bin/sh as the default shell for this queue.
  600. Submit time environment variables are passed directly to the running job, so are shell independent.
  601. X.SH OPTIONS
  602. X.TP 12
  603. X.B  \-f
  604. Toggle the fixed context flag for this queue.
  605. If the queue does not exist (is being created in this operation)
  606. then the -f option will cause the fixed context flag to be set (Default is not set).
  607. If the queue already exists, the -f option will toggle the state of the
  608. fixed context flag.
  609. X.TP
  610. X.BI \-m " monitor"
  611. Specify a default monitor for this queue.
  612. monitor may be a directory, or a file. If monitor is a directory,
  613. the file xxxx.mon will be appended where xxxx is the first
  614. four characters of the queue file name.
  615. The maximum length of the entered path is 63 characters.
  616. If the queue does not exist (is being created in this operation)
  617. and -m is not specified then a monitor xxxx.mon in the 
  618. spooling directory will be used.
  619. X.sp
  620. A special case is if the monitor specified is "NONE" (in upper case).
  621. In this case the user submitting a job to the queue MUST provide a 
  622. monitor specification, either by using the -m option of js, or through
  623. an environment variable MONITOR.
  624. X.TP
  625. X.BI \-p " priority"
  626. Specify a priority or 'nice value' at which jobs processed
  627. in this queue will be run. The priority is a value between -20, and 19
  628. and is the increment by which the nice value of the running qp activity
  629. is adjusted when the job is executed. Low values increase the scheduling priority
  630. of the kernel, high values decrease it. (See the man page for nice()).
  631. If the queue does not exist (is being created in this operation)
  632. and -p is not specified priority will be 0.
  633. X.TP
  634. X.BI \-s " spoolpath"
  635. Specify an alternate directory in which to create the jcl
  636. files for jobs processed in this queue.       
  637. The maximum length of the entered path is 63 characters.
  638. If the queue does not exist (is being created in this operation)
  639. and -s is not specified, then the default defined as SPOOLPATH
  640. in qbatch.h will be used.
  641. X.TP
  642. X.BI \-v
  643. Display QBATCH version and copyright information.
  644. X.SH FILES
  645. X.ft B
  646. QUEUEPATH/*
  647. X.SH "SEE ALSO"
  648. X.BR qbatch (1L)
  649. X.BR jj (1L)
  650. X.BR jk (1L)
  651. X.BR jm (1L)
  652. X.BR jn (1L)
  653. X.BR jr (1L)
  654. X.BR js (1L)
  655. X.BR qa (1L)
  656. X.BR qd (1L)
  657. X.BR qe (1L)
  658. X.BR qf (1L)
  659. X.BR qg (1L)
  660. X.BR qh (1L)
  661. X.BR ql (1L)
  662. X.BR qp (1L)
  663. X.BR qs (1L)
  664. X.BR qt (1L)
  665. X.BR qw (1L)
  666. X.BR rc.QBATCH (8L)
  667. X.BR jobdone (8L)
  668. X.BR queue (5L)
  669. X.BR qxenv (5L)
  670. END_OF_FILE
  671. if test 5942 -ne `wc -c <'man/qc.l'`; then
  672.     echo shar: \"'man/qc.l'\" unpacked with wrong size!
  673. fi
  674. # end of 'man/qc.l'
  675. fi
  676. if test -f 'src/config.c' -a "${1}" != "-c" ; then 
  677.   echo shar: Will not clobber existing file \"'src/config.c'\"
  678. else
  679. echo shar: Extracting \"'src/config.c'\" \(6588 characters\)
  680. sed "s/^X//" >'src/config.c' <<'END_OF_FILE'
  681. X/************************************************************************/
  682. X/*                                                                      */
  683. X/*   config.c source file differences for varying library support.      */
  684. X/*                                                                      */
  685. X/*   Copyright (c) Vita Services 1990                                   */
  686. X/*             (c) Vita Fibres   1990 1991                              */
  687. X/*                                                                      */
  688. X/************************************************************************/
  689. X#include <signal.h>
  690. X#include "config.h"
  691. X#include "qbatch.h"
  692. int fpq, had_usersig, lastflags;
  693. pid_t childid;
  694. extern char queue[];
  695. extern char queuename[];
  696. void q_version()
  697. X{
  698. X    puts (&QbSID[5]);
  699. X    puts ("");
  700. X    puts (&QbCR1[5]);
  701. X    puts (&QbCR2[5]);
  702. X    puts ("");
  703. X    exit(0);
  704. X}
  705. int bad_queue()
  706. X{
  707. X    if (strcmp (head.q_magic, "qBq") != 0)
  708. X    {
  709. X        fprintf(stderr,"%s is not a valid QBATCH queue\007\n", queuename);
  710. X        return(-1);
  711. X    }
  712. X    return(0);
  713. X}
  714. void tell_qp()
  715. X/* included here simply because this is where signal.h is defined */
  716. X{
  717. X    if (head.qh_pid) kill (head.qh_pid, SIGUSR1);
  718. X}
  719. X
  720. X#ifdef NOTRUNC
  721. int ftruncate(fd, size)
  722. int fd;
  723. long size;
  724. X{return(0);}
  725. X#endif /* NOTRUNC */
  726. X
  727. X#ifdef NO_PGP
  728. void qb_setpgrp()
  729. X{
  730. X    return;
  731. X}
  732. void kill_child_group()
  733. X{
  734. X    kill (childid, SIGKILL);
  735. X}
  736. void toggle_halt_status(newaction)
  737. int newaction;
  738. X{
  739. X    kill (childid, (((newaction &qh_halt) == 0) ? SIGCONT : SIGSTOP));
  740. X}
  741. X#endif /* NO_PGP */
  742. X
  743. X#ifdef SUNOSPGP
  744. void qb_setpgrp()
  745. X{
  746. X    setpgrp(0);
  747. X}
  748. void kill_child_group()
  749. X{
  750. X    killpg (childid, SIGKILL);
  751. X}
  752. void toggle_halt_status(newaction)
  753. int newaction;
  754. X{
  755. X    killpg (childid, (((newaction &qh_halt) == 0) ? SIGCONT : SIGSTOP));
  756. X}
  757. X#endif /* SUNOSPGP */
  758. X
  759. X#ifdef XPG3PGP
  760. void qb_setpgrp()
  761. X{
  762. X    setpgid(0, 0);
  763. X}
  764. void kill_child_group()
  765. X{
  766. X    kill ((childid * -1), SIGKILL);
  767. X}
  768. void toggle_halt_status(newaction)
  769. int newaction;
  770. X{
  771. X    kill ((childid * -1), (((newaction &qh_halt) == 0) ? SIGCONT : SIGSTOP));
  772. X}
  773. X#endif /* XPG3PGP */
  774. X
  775. X#ifdef LOCKF
  776. void q_lock(fd)
  777. int fd;
  778. X{
  779. X    lockf (fd, F_LOCK, 0);
  780. X}
  781. X
  782. void q_unlock(fd)
  783. int fd;
  784. X{
  785. X    lockf (fd, F_ULOCK, 0);
  786. X}
  787. int q_islock(fd)
  788. int fd;
  789. X/* check if the file is locked, return 0 if not locked, non 0 if locked */
  790. X{
  791. X    return (lockf(fd, F_TEST, 0));
  792. X}
  793. X#endif /* LOCKF */
  794. X
  795. X#ifdef FLOCK
  796. X#include <sys/file.h>
  797. void q_lock(fd)
  798. int fd;
  799. X{
  800. X    flock (fd, LOCK_EX);
  801. X}
  802. void q_unlock(fd)
  803. int fd;
  804. X{
  805. X    flock (fd, LOCK_UN);
  806. X}
  807. int q_islock(fd)
  808. int fd;
  809. X/* check if the file is locked, return 0 if not locked, non 0 if locked */
  810. X{
  811. X    return (flock(fd, LOCK_EX|LOCK_NB);
  812. X}
  813. X#endif /* FLOCK */
  814. X
  815. X#ifdef FCNTL
  816. X#include <fcntl.h>
  817. struct flock f_lock;
  818. void q_lock(fd)
  819. int fd;
  820. X{
  821. X    f_lock.l_type   = F_WRLCK;
  822. X    f_lock.l_whence = SEEK_SET;
  823. X    f_lock.l_start  = 0;
  824. X    f_lock.l_len    = 0;
  825. X    /* apply wait lock, if it fails (only via signal) try again) */
  826. X    while (fcntl (fd, F_SETLKW, &f_lock) == -1);
  827. X}
  828. void q_unlock(fd)
  829. int fd;
  830. X{
  831. X    f_lock.l_type = F_UNLCK;
  832. X    fcntl (fd, F_SETLK, f_lock);
  833. X}
  834. int q_islock(fd)
  835. int fd;
  836. X/* check if the file is locked, return 0 if not locked, non 0 if locked */
  837. X{
  838. X    f_lock.l_type   = F_WRLCK;
  839. X    f_lock.l_whence = SEEK_SET;
  840. X    f_lock.l_start  = 0;
  841. X    f_lock.l_len    = 0;
  842. X    return (fcntl (fd, F_SETLK, &f_lock));
  843. X}
  844. X#endif /* FCNTL */
  845. void qb_resetterm();
  846. void qb_term (value)
  847. int value;
  848. X{
  849. X    if (fpq > 0)
  850. X    {
  851. X        q_unlock(fpq);
  852. X        close (fpq);
  853. X    fpq = 0;
  854. X    }
  855. X    if (fpq = 0)
  856. X    {
  857. X        fpq = open (queue, O_RDWR);
  858. X        q_lock(fpq);
  859. X        read (fpq, &head, sizeof (head));
  860. X        lseek (fpq, 0, SEEK_SET);
  861. X        write (fpq, &head, sizeof (head));
  862. X        fpq = 0;
  863. X    }
  864. X    qb_resetterm();
  865. X    exit (value);
  866. X}
  867. X
  868. void qb_exit ()
  869. X/* Interrupt handler for SIGINT to ensure clean closedown */
  870. X{
  871. X    qb_term (-1);
  872. X}
  873. X
  874. X#ifdef SIGACTION
  875. X
  876. void qb_handle (fun, sig)
  877. HANDLER_TYPE (*fun)();
  878. int sig;
  879. X{
  880. X    struct sigaction actsig;
  881. X    sigemptyset(&actsig.sa_mask);
  882. X    actsig.sa_flags = 0;
  883. X    actsig.sa_handler = (HANDLER_TYPE (*)())fun;
  884. X    sigaction(sig, actsig, (struct sigaction *) NULL);
  885. X}
  886. X
  887. X#endif /* SIGACTION */
  888. X
  889. X#ifdef SIGSET
  890. void qb_handle(fun, sig)
  891. HANDLER_TYPE (*fun)();
  892. int sig;
  893. X{
  894. X    sigset(sig, (HANDLER_TYPE (*)())fun);
  895. X}
  896. X#endif /* SIGSET */
  897. X
  898. X#ifdef SIGNAL /* WARNING ** older SYSV versions of signal reset the signal */
  899. X              /* handler to SIG_DFL when a signal is taken.. if this is    */
  900. X              /* the case #define RE_INSTALL */
  901. void qb_handle(fun, sig)
  902. HANDLER_TYPE (*fun)();
  903. int sig;
  904. X{
  905. X    signal(sig, (HANDLER_TYPE (*)())fun);
  906. X}
  907. X#endif /* SIGNAL */
  908. X
  909. X#ifdef SIGVEC
  910. void qb_handle(fun, sig)
  911. HANDLER_TYPE (*fun)();
  912. int sig;
  913. X{
  914. X    struct sigvec actsig;
  915. X    actsig.sv_mask) = 0
  916. X    actsig.sv_flags = 0;
  917. X    actsig.sv_handler = (HANDLER_TYPE (*)())sig;
  918. X    sigvec(sig, actsig, (struct sigvec *) NULL);
  919. X}
  920. X#endif /* SIGVEC */
  921. void qb_resetterm()
  922. X{
  923. X    qb_handle (SIG_DFL, SIGABRT);
  924. X    qb_handle (SIG_DFL, SIGHUP);
  925. X    qb_handle (SIG_DFL, SIGTRAP);
  926. X    qb_handle (SIG_DFL, SIGILL);
  927. X    qb_handle (SIG_DFL, SIGSEGV);
  928. X    qb_handle (SIG_DFL, SIGTERM);
  929. X    qb_handle (SIG_DFL, SIGQUIT);
  930. X    qb_handle (SIG_DFL, SIGINT);
  931. X}        
  932. X
  933. X/* setup terminal handler for untoward exit */
  934. void qb_setterm()
  935. X{
  936. X    qb_handle (qb_exit, SIGABRT);
  937. X    qb_handle (qb_exit, SIGHUP);
  938. X    qb_handle (qb_exit, SIGTRAP);
  939. X    qb_handle (qb_exit, SIGILL);
  940. X    qb_handle (qb_exit, SIGSEGV);
  941. X    qb_handle (qb_exit, SIGTERM);
  942. X    qb_handle (qb_exit, SIGQUIT);
  943. X    qb_handle (qb_exit, SIGINT);
  944. X}        
  945. X
  946. void qb_setuser(fun)
  947. void (*fun)();
  948. X{
  949. X    had_usersig = 0;
  950. X    qb_handle (fun, SIGUSR1);
  951. X}
  952. void qb_resetusr()
  953. X{
  954. X    qb_handle (SIG_DFL, SIGUSR1);
  955. X}
  956. X#ifdef WAIT_XPG3
  957. X#include <sys/wait.h>
  958. void q_wait(message)
  959. char message[];
  960. X{
  961. X    int waitid;
  962. X    WAIT_TYPE wstatus;
  963. X    while (1)
  964. X    {
  965. X        waitid =  wait (&wstatus);
  966. X        if (had_usersig)
  967. X        {
  968. X#ifdef RE_INSTALL
  969. X        setuser();
  970. X#endif
  971. X        }
  972. X        if (waitid != childid) continue;
  973. X        if (WIFSTOPPED (wstatus) && (lastflags & qh_halt))
  974. X        { /* suspend processing signal ignore it */
  975. X            continue;
  976. X        }
  977. X        if (WIFEXITED (wstatus)   /* has it exited  */
  978. X        || WIFSIGNALED (wstatus)) /* or been killed */
  979. X        break;
  980. X    }
  981. X    if (WIFEXITED (wstatus))
  982. X    sprintf (message, "Job exited with status %d", WEXITSTATUS (wstatus));
  983. X    if (WIFSIGNALED (wstatus))
  984. X    sprintf (message, "Job killed by signal %d", WTERMSIG (wstatus));
  985. X}
  986. X#endif /* WAIT_XPG3 */
  987. void qb_pause()
  988. X{
  989. X#ifdef SIGPAUSE
  990. X    sigpause(0);
  991. X#else
  992. X    pause();
  993. X#endif
  994. X#ifdef RE_INSTALL
  995. X    qb_setuser()    /* re-install interrupt handler */
  996. X#endif /* RE_INSTALL */
  997. X}
  998. END_OF_FILE
  999. if test 6588 -ne `wc -c <'src/config.c'`; then
  1000.     echo shar: \"'src/config.c'\" unpacked with wrong size!
  1001. fi
  1002. # end of 'src/config.c'
  1003. fi
  1004. if test -f 'src/config.h' -a "${1}" != "-c" ; then 
  1005.   echo shar: Will not clobber existing file \"'src/config.h'\"
  1006. else
  1007. echo shar: Extracting \"'src/config.h'\" \(7187 characters\)
  1008. sed "s/^X//" >'src/config.h' <<'END_OF_FILE'
  1009. X/************************************************************************/
  1010. X/*                                                                      */
  1011. X/*   config.h                                                           */
  1012. X/*                                                                      */
  1013. X/*   Copyright (c) Vita Services 1990                                   */
  1014. X/*             (c) Vita Fibres   1990 1991                              */
  1015. X/*                                                                      */
  1016. X/************************************************************************/
  1017. X
  1018. X/* This file contains configurable functions depending on the facilities     */
  1019. X/* available in your system libraries. Each group of functions should have   */
  1020. X/* ONE (and only one) #define set. Those which are the preferred method      */
  1021. X/* according to the X-OPEN (tm) programming guides version 3 are marked XPG3 */
  1022. X
  1023. X/* In order to allow you to configure QBATCH for your system, a brief        */
  1024. X/* description of the requirements is included in each section. I would      */
  1025. X/* rather you didn't go hacking over the individual function code sections in*/
  1026. X/* config.c. If your system cannot be configured using the existing #defines */
  1027. X/* and code, add another #define or two, and the corresponding code sections.*/
  1028. X
  1029. X/*---------------------------------------------------------------------------*/
  1030. X/* Proces group calls (define only one)
  1031. X/* Allow a signal (SIGKILL, SIGHALT, or SIGCONT) sent to a running job, to be
  1032. X/* also sent to any children that job may have forked.
  1033. X
  1034. X/*#define SUNOSPGP*/    /* setpgrp() and killpg() */
  1035. X#define XPG3PGP        /* setpgid() and kill() with negative pid    XPG3 */
  1036. X
  1037. X/*#define NO_PGP */    /* some poor misbegotten systems don't support process*/
  1038. X            /* groups. If this is defined, signals generated by qp*/
  1039. X            /* in response to qh, qg, jk etc will only be sent to */
  1040. X            /* the job itself. If the job forks children, they    */
  1041. X            /* will have to be cleaned up manually.               */
  1042. X/*---------------------------------------------------------------------------*/
  1043. X/* File locking calls  (define only one) */
  1044. X
  1045. X/* Prevent multiple updates and/or reads of the queue file by applying a     */
  1046. X/* 'wait' lock. (Activity calling for a lock is blocked until a lock is      */
  1047. X/* available. Locks are freed as soon as possible, and freed by a signal     */
  1048. X/* handler if the program terminates abnormally) */
  1049. X
  1050. X#define FCNTL        /* use fcntl() calls for file locking (XPG3) */
  1051. X
  1052. X/*#define FLOCK*/    /* use flock() calls */
  1053. X
  1054. X/*#define LOCKF*/    /* use lockf() calls */
  1055. X
  1056. X/*---------------------------------------------------------------------------*/
  1057. X/* Pause awaiting signal calls       */
  1058. X/* If the handler needs to be re-installed, define RE_INSTALL) */
  1059. X
  1060. X/* When the queue is idle, the queue process engine 'goes to sleep' until    */
  1061. X/* a SIGUSR1 is received from a support program. After receiving the signal, */
  1062. X/* the signal handler may have to be re-installed. */
  1063. X
  1064. X/* the actual call used to pause (define SIGPAUSE if sigpause(0) is to be used */
  1065. X/* comment out the definition if the (XPG) pause() call ist to be used */
  1066. X/* #define SIGPAUSE  */
  1067. X
  1068. X/* if the signal handler is reset to SIG_DFL when an interrupt has been */
  1069. X/* received, the signal handler will need to be re-installed each time. */
  1070. X/* if this is the case, uncomment the following #define */
  1071. X/*#define RE_INSTALL */
  1072. X
  1073. X/*---------------------------------------------------------------------------*/
  1074. X/* signal handling calls (define one of these) */
  1075. X
  1076. X/* Signal handling functions are used in two ways in QBATCH */
  1077. X/* first, to release any held locks on the queue files in case of abnormal */
  1078. X/* termination, so that other programs are not held in a deadlock */
  1079. X/* and secondly to trigger a (maybe idle) queue process engine into acting */
  1080. X/* on changes of status in a queue. */
  1081. X/* the first of these will only ever be called once (when the program      */
  1082. X/* terminates) so does not need to remain installed when it is triggered.  */
  1083. X/* the second MUST ALWAYS BE ACTIVE!! If the process engine is idle, the   */
  1084. X/* support programs will send a SIGUSR1 to it's pid to wake it up. If the  */
  1085. X/* signal handling functions reset the signal handler to SIG_DFL when a    */
  1086. X/* signal is trapped, then it MUST BE REINSTALLED!! (#define RE_INSTALL    */
  1087. X/* above.) The variable 'had_usersig' is set in the handler so that pause  */
  1088. X/* and wait routines can check if the handler needs to be re-installed.    */
  1089. X
  1090. X/*#define SIGACTION*/    /* XPG3 */
  1091. X#define SIGSET
  1092. X/*#define SIGVEC */
  1093. X/*#define SIGNAL */
  1094. X/* the type of the handler function can vary from system to system. it is   */
  1095. X/* usually either void or int */
  1096. X/*typedef void HANDLER_TYPE;*/
  1097. typedef int HANDLER_TYPE;
  1098. X
  1099. X/*---------------------------------------------------------------------------*/
  1100. X/* wait calls (define one of these) */
  1101. X
  1102. X/* at this time there is only one define for wait calls, it is included here */
  1103. X/* to take advantage of the RE_INSTALL #define. The function q_wait(ptr) will*/
  1104. X/* wait for a child process to die, and will store in *ptr an appropriate    */
  1105. X/* message to be written to the queue monitor. If the wait call is           */
  1106. X/* interrupted by another signal, it checks had_usersig and RE_INSTALL to    */
  1107. X/* determine what other action to take. If the signal indicates that the     */
  1108. X/* has stopped rather than exited, the function loops */
  1109. X/* if you have wait functionality that does not return the exit status of a  */
  1110. X/* child (?????) then your function should make *ptr NULL */
  1111. X
  1112. X/* the status location of a wait call can vary from system to system, older  */
  1113. X/* versions used a 'union wait', newer ones use int (and some systems use an */
  1114. X/* int but have not changed the analysis macros, so they're still trying to  */
  1115. X/* analyse a union wait out of an int without casting it first!!)            */
  1116. X
  1117. X/*typedef int WAIT_TYPE; */    /* XPG3 */
  1118. typedef union wait WAIT_TYPE;
  1119. X
  1120. X#define WAIT_XPG3    /* XPG3 */
  1121. X
  1122. X/*---------------------------------------------------------------------------*/
  1123. X/* if your system does NOT have the ftruncate or chsize call to adjust the size */
  1124. X/* of an open file, define this */
  1125. X/*#define NOTRUNC */
  1126. X/* in config.c, ftruncate is a dummy (empty) function, which is compiled if NOTRUNC */
  1127. X/* is defined. If you feel you can create the functionality of ftruncate, you are */
  1128. X/* welcome to add code to this function.*/
  1129. X
  1130. X/* if your system has chsize() instead of ftruncate define this */
  1131. X/*#define ftruncate(a,b) (whatever your call is where a is the open fd, and b is the size) */
  1132. X/*---------------------------------------------------------------------------*/
  1133. X/* time calls (define one of these) */
  1134. X
  1135. X/* what we need here is the clock tick of the system. the result of what is  */
  1136. X/* defined here is placed into a variable in time.c                     */
  1137. X
  1138. X#define QCLOCK_TICK sysconf(_SC_CLK_TCK);
  1139. X/*define QCLOCK_TICK CLK_TCK */
  1140. X/*define QCLOCK_TICK gethz();*/
  1141. X
  1142. X/* Some systems don't define pid_t, if not typedef it here */
  1143. X/*typedef int pid_t*/
  1144. X/* and some don't define these */
  1145. X/*typedef short uid_t*/
  1146. X/*typedef short gid_t*/
  1147. X
  1148. X/* if needed , define these */
  1149. X
  1150. X/*#define strchr index */
  1151. X/*#define strrchr rindex */
  1152. END_OF_FILE
  1153. if test 7187 -ne `wc -c <'src/config.h'`; then
  1154.     echo shar: \"'src/config.h'\" unpacked with wrong size!
  1155. fi
  1156. # end of 'src/config.h'
  1157. fi
  1158. if test -f 'src/jj.c' -a "${1}" != "-c" ; then 
  1159.   echo shar: Will not clobber existing file \"'src/jj.c'\"
  1160. else
  1161. echo shar: Extracting \"'src/jj.c'\" \(5752 characters\)
  1162. sed "s/^X//" >'src/jj.c' <<'END_OF_FILE'
  1163. X/************************************************************************/  
  1164. X/*                                                                      */
  1165. X/* jj .. Job jump. move an entry towards the front of the queue.        */
  1166. X/*                                                                      */
  1167. X/*      usage: jj [-e <entryno>]  qname                                 */
  1168. X/*                                                                      */
  1169. X/*   Copyright (c) Vita Services 1990                                   */
  1170. X/*             (c) Vita Fibres   1990 1991                              */
  1171. X/*                                                                      */
  1172. X/************************************************************************/
  1173. X
  1174. X#include "qbatch.h"
  1175. int fpq = 0;
  1176. int i, l;
  1177. int killed = 0;
  1178. long  j, k;
  1179. int aflag = 0, kflag = 0;
  1180. pid_t jpid = 0;
  1181. uid_t userid = 0, entryno = 0;
  1182. off_t *entries;
  1183. uid_t   *uids;
  1184. char queue[128];
  1185. char *queuename;
  1186. char buff [128];                            
  1187. struct queue_entry entry1;                            
  1188. X#include "config.h"
  1189. X
  1190. main (argc, argv)
  1191. int argc;
  1192. char *argv[];
  1193. X{
  1194. X    int c;
  1195. X    extern char *optarg;
  1196. X    extern int optind;
  1197. X    if (argc == 1)
  1198. X    {
  1199. X        puts ("Usage: jj -e <entryno>  qname");
  1200. X        qb_term (0);
  1201. X    }
  1202. X    while ((c = getopt (argc, argv, "e:v")) != -1)
  1203. X    switch (c)
  1204. X    {
  1205. X        case 'e':   entryno = atoi(optarg);
  1206. X                    break;                    
  1207. X        case 'v':   q_version();
  1208. X    case '?':   qb_term (-1);
  1209. X    }
  1210. X    if (optind >= argc)
  1211. X    {
  1212. X        fprintf (stderr, "Missing queue name\n");
  1213. X        qb_term (-1);
  1214. X    }
  1215. X    if (entryno == 0)
  1216. X    {
  1217. X        fprintf (stderr, "-e (entry number) required for jump\n");
  1218. X        qb_exit (-1);
  1219. X    }
  1220. X
  1221. X    queuename = argv[optind];
  1222. X    strcpy (queue, QUEUEPATH);
  1223. X    strcat (queue, queuename);
  1224. X    qb_setterm();
  1225. X    fpq = open (queue, O_RDWR);
  1226. X    if (fpq == -1)
  1227. X    {
  1228. X        fprintf (stderr, "Invalid queue name: %s\n", queuename);
  1229. X        qb_term (-1); 
  1230. X    }
  1231. X    q_lock(fpq);
  1232. X    read  (fpq, &head, sizeof(head));
  1233. X    if (bad_queue()) qb_exit(-1);
  1234. X    if (head.qh_noentries == 0)
  1235. X    {
  1236. X        fprintf (stderr, " Queue %s is empty!\n", queuename);
  1237. X        qb_term (-1);
  1238. X    }
  1239. X    userid = getuid();
  1240. X    if ((head.qh_flags&qh_halt)  == 0)
  1241. X    {
  1242. X        head.qh_flags += qh_halt;
  1243. X        lseek (fpq, 0, SEEK_SET);
  1244. X        write (fpq, &head, sizeof(head));
  1245. X        q_unlock(fpq);
  1246. X        close (fpq);fpq = 0;
  1247. X        tell_qp();
  1248. X    }
  1249. X    do
  1250. X    {
  1251. X        fpq = open (queue, O_RDWR);
  1252. X    q_lock(fpq);
  1253. X        read  (fpq, &head, sizeof(head));
  1254. X        read  (fpq, &entry, sizeof(entry));
  1255. X        jpid = entry.qe_status;
  1256. X        if (jpid != 0)  /* something running */
  1257. X        {
  1258. X        q_unlock(fpq); /* and is the right job! */
  1259. X        close (fpq);fpq = 0;
  1260. X            fpq = open (queue, O_RDWR);
  1261. X        q_lock(fpq);
  1262. X            read  (fpq, &head, sizeof(head));
  1263. X        if (head.qh_noentries == 0)
  1264. X            {
  1265. X                    fprintf (stderr, " Queue %s is empty!\n", queuename);
  1266. X                    qb_term (-1);
  1267. X                }
  1268. X            read  (fpq, &entry, sizeof(entry));
  1269. X            if ((entry.qe_status != jpid) && (jpid != 0))   /* job has changed */
  1270. X            {
  1271. X                jpid = 0;                  /* don't kill */
  1272. X            }
  1273. X        }
  1274. X    }
  1275. X    while (jpid != entry.qe_status)    ;
  1276. X    /* the current job is halted */
  1277. X    entries = (off_t *) calloc ((head.qh_noentries+1), sizeof(off_t));
  1278. X    uids =    (uid_t *) calloc   ((head.qh_noentries+1), sizeof(off_t));
  1279. X    lseek (fpq, sizeof(head), SEEK_SET);
  1280. X    l = 0;
  1281. X    for (i = 0; i < head.qh_noentries; i++)
  1282. X    {
  1283. X        j = lseek (fpq, 0L, SEEK_CUR);
  1284. X        read (fpq, &entry, sizeof(entry));
  1285. X        if (entry.qe_jobno == entryno) 
  1286. X        {
  1287. X            l = i;
  1288. X            if ((userid != 0) && (userid != entry.qe_uid))
  1289. X            {
  1290. X                fprintf (stderr, "Can't jump another's job\n");
  1291. X                qb_exit (-1);
  1292. X            }
  1293. X        }
  1294. X        entries[i] = j;
  1295. X        uids   [i] = entry.qe_uid;
  1296. X    }
  1297. X    if (l == 0)
  1298. X    {
  1299. X        fprintf (stderr, "Queue %s entry %d not found\n",queuename, entryno);
  1300. X        qb_term (-1);
  1301. X    }
  1302. X    /* we now have a table (entries) containing the offsets of those wanted */
  1303. X    lseek (fpq, entries[l], SEEK_SET);
  1304. X    read (fpq, &entry1, sizeof(entry1)); /* get jumped record */
  1305. X    for (i=l; i > 1; i--)
  1306. X    {
  1307. X        if ((userid == 0) || (userid == uids [i-1]))
  1308. X        {/* we can jump it */
  1309. X            lseek (fpq, entries[i-1], SEEK_SET);
  1310. X            read (fpq, &entry, sizeof(entry));
  1311. X            write(fpq, &entry, sizeof(entry));
  1312. X        }
  1313. X        else 
  1314. X        {
  1315. X            lseek (fpq, entries[i], SEEK_SET);
  1316. X            write (fpq, &entry1, sizeof(entry1));
  1317. X            break;
  1318. X        }
  1319. X    }
  1320. X    if (i == 1)
  1321. X    {
  1322. X        if ((jpid == 0) && ((userid == 0) || (userid == uids [i-1])))
  1323. X        {/* we can jump it */
  1324. X            lseek (fpq, entries[i-1], SEEK_SET);
  1325. X            read (fpq, &entry, sizeof(entry));
  1326. X            write(fpq, &entry, sizeof(entry));
  1327. X            lseek (fpq, entries[i-1], SEEK_SET);
  1328. X            write(fpq, &entry1, sizeof(entry1));
  1329. X            i--;
  1330. X        }
  1331. X        else 
  1332. X        {
  1333. X            lseek (fpq, entries[i], SEEK_SET);
  1334. X            write (fpq, &entry1, sizeof(entry1));
  1335. X        }
  1336. X    }
  1337. X    if (i == l)
  1338. X    {
  1339. X        fprintf (stderr, "Queue %s can't jump entry no %d\n", queuename, entryno);
  1340. X        qb_exit (0);
  1341. X    }
  1342. X    k = lseek (fpq, sizeof(head), SEEK_SET);
  1343. X    
  1344. X    lseek (fpq, 0, SEEK_SET);
  1345. X    if ((head.qh_flags & qh_halt) != 0)
  1346. X    {
  1347. X        head.qh_flags -= qh_halt;
  1348. X    }
  1349. X
  1350. X    write (fpq, &head, sizeof(head));
  1351. X
  1352. X
  1353. X/* right, now either kill or continue first entry (if running) */
  1354. X    q_unlock(fpq);
  1355. X    close (fpq);fpq = 0;
  1356. X    tell_qp();
  1357. X    exit (0);
  1358. X}
  1359. END_OF_FILE
  1360. if test 5752 -ne `wc -c <'src/jj.c'`; then
  1361.     echo shar: \"'src/jj.c'\" unpacked with wrong size!
  1362. fi
  1363. # end of 'src/jj.c'
  1364. fi
  1365. echo shar: End of archive 4 \(of 6\).
  1366. cp /dev/null ark4isdone
  1367. MISSING=""
  1368. for I in 1 2 3 4 5 6 ; do
  1369.     if test ! -f ark${I}isdone ; then
  1370.     MISSING="${MISSING} ${I}"
  1371.     fi
  1372. done
  1373. if test "${MISSING}" = "" ; then
  1374.     echo You have unpacked all 6 archives.
  1375.     rm -f ark[1-9]isdone
  1376. else
  1377.     echo You still need to unpack the following archives:
  1378.     echo "        " ${MISSING}
  1379. fi
  1380. ##  End of shell archive.
  1381. exit 0
  1382.  
  1383. exit 0 # Just in case...
  1384. -- 
  1385. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1386. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1387. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1388. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1389.